package com.ant.xmla.datacrawling.utils.http;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ant.xmla.datacrawling.dto.VipUrlDto;
import com.ant.xmla.datacrawling.utils.cache.RedisUtil;
import com.ant.xmla.datacrawling.utils.encryption.VipEncryption;
import com.ant.xmla.datacrawling.utils.fileUtli.FileReadWriteUtil;
import com.ant.xmla.datacrawling.utils.fileUtli.PropertiesUtil;
import com.ant.xmla.datacrawling.utils.pageUtil.PageDevice;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

import static com.ant.xmla.datacrawling.utils.fileUtli.FileReadWriteUtil.createFile;

/**
* @Description:请求工具类
* @Author:wkl
* @Date:2020/9/4
* @param:
* @return:
*/
public class HttpClientUtils {

    private static  Date date = new Date();//获取当前时间

    private static String cookie = PropertiesUtil.getDocking("COOKIE");

    private static Calendar calendar = Calendar.getInstance();
    /**
    * @Description:字符集
    * @Author:wkl
    * @Date:2020/9/4
    * @param:
    * @return:
    */
    private static final String CHARSET_ENCODING="UTF-8";

    private static String homePageUrl = PropertiesUtil.getDocking("Home_Page_Url");

    /**
     * @Description:设置随机数
     * @Author:wkl
     * @Date:2020/9/4
     * @param:
     * @return:
     */
    private static Random random = new Random();

    /**
     * @Description:查询接口通过这个接口进行单个书本爬取信息,返回书籍的id信息
     * @Author:中国蚂蚁技术有限公司
     * @Date: 2020/9/13 11:08
     * @Param:  [] https://www.ximalaya.com/revision/search/main?core=all&kw=%E8%B7%AF%E9%81%A5&spellchecker=true&device=iPhone
     * @return: java.lang.String
     * */
    public static Integer inquire(String param){
        String oneTrack = PropertiesUtil.getDocking("QUERY_ONE_TRACK");
        try {
//            String encodeParam = URLEncoder.encode(param, "UTF-8");
            StringBuilder url = new StringBuilder();
            url.append(homePageUrl);
            url.append(oneTrack);
            url.append(param);
            url.append("&spellchecker=true&device=iPhone");
            System.out.println(url.toString());
            String responseParam = sendRequestGet(url.toString());
            if (responseParam.contains("{")) {
                JSONObject parseObject = JSONObject.parseObject(responseParam);
                if (parseObject.getInteger("ret") == 200) {
                    JSONArray parseData = parseObject.getJSONObject("data").getJSONObject("album").getJSONArray("docs");
                    JSONObject parseJSON = parseData.getJSONObject(0);
                    Integer albumId = parseJSON.getInteger("albumId");
                    return albumId;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
            return 0;
    }

    /**
    * @Description:获取服务器时间戳
    * @Author:wkl
    * @Date:2020/9/4
    * @param:
    * @return:java.lang.String
    */
    public static String getTimestamp(){
        //获取时间戳路径
        StringBuilder url = new StringBuilder();
        String timestampUrl = PropertiesUtil.getDocking("Timestamp_url");
        url.append(homePageUrl);
        url.append(timestampUrl);
        System.out.println("获取服务器时间戳路径："+url.toString());

        HttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url.toString());
        httpGet.setHeader("content-type","application/x-www-form-urlencoded;charset=UTF-8");
        httpGet.setHeader("user-agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4128.3 Safari/537.36");
        HttpResponse response = null;
        try {
            ResponseResult responseResult = httpClient.execute(httpGet, responseHandler);
            if(responseResult.getCode()==200){
                System.out.println("获取返回数据："+responseResult.getResult());
                return responseResult.getResult();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
    * @Description:获取token
    * @Author:wkl
    * @Date:2020/9/4
    * @param:
     * @说明： //喜马拉雅加密规则 md5(ximalaya-服务器时间戳)(100以内随机数)服务器时间戳(100以内随机数)现在时间戳
     *  有过期时间时间为40秒 40秒需要重新获取
    * @return:java.lang.String
    */
    public static String getToken(){
        String timestampOne = getTimestamp();
        String timestampTwo = getTimestamp();
        String param = "himalaya-"+timestampOne;

        String digestParam = DigestUtils.md5DigestAsHex(param.getBytes());
        //获取随机数 100以内
        int num1 = random.nextInt(99) + 1;
        int num2 = random.nextInt(99) + 1;
        //拼接
        StringBuilder xmSign = new StringBuilder();
        xmSign.append(digestParam);
        xmSign.append("("+num1+")");
        xmSign.append(timestampOne);
        xmSign.append("("+num2+")");
        xmSign.append(timestampTwo);
        return xmSign.toString();
    }

    /**
     * @Description:使用jsoup获取页面中的url
     * @Author:wkl
     * @Date:2020/9/4
     * @param:
     * @return:
     */
    public static List<String> getBookUrlO(){
        try {
            List<String> list = new ArrayList<>();
            Document document = Jsoup.connect("https://www.ximalaya.com/youshengshu/wenxue/").ignoreContentType(true).userAgent("Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.15)").timeout(5000).get();
            Elements hrefSelect = document.select("a.album-cover.vn_");
            String url = null;
            for (Element element : hrefSelect) {
                String bookHref = element.getElementsByTag("a").attr("href");
                //分割字符串
                url = bookHref.substring(bookHref.indexOf("/", 1)+1, bookHref.length() - 1);
                list.add(url);
            }
            return list;
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * @Description:调用接口返回书籍信息数据 json格式 返回路径
     * @Author:中国蚂蚁技术有限公司
     * @Date: 2020/9/4 22:42
     * @Param: 分页获取数据 page第几页，total多少条
     * @return: java.util.List<java.lang.String>
     * */
    public static Map<Integer,List<String>> getBookUrlT(){
        Map<Integer,List<String>> map = new HashMap<>();
        //category=youshengshu&subcategory=wenxue&meta=&sort=0&page=1&perPage=30
        //page=1&perPage=30
        //请求方式为get
        String queryListUrl = PropertiesUtil.getDocking("QUERY_LIST_URL");
        StringBuilder getBookInfoUrl = new StringBuilder();
        getBookInfoUrl.append(homePageUrl);
        getBookInfoUrl.append(queryListUrl);
        System.out.println("分页请求路径:"+getBookInfoUrl.toString());
        //发送请求 获取String格式
        String responseParam = sendRequestGet(getBookInfoUrl.toString());
        //判断解析将String转换为JSON格式
        if (responseParam.contains("{")){
            JSONObject parseParam = JSONObject.parseObject(responseParam);
            if ("200".equals(parseParam.getString("ret"))) {
                //请求成功 设值返回参数获取结果
                JSONObject dataParam = parseParam.getJSONObject("data");
                JSONArray albumsListParam = dataParam.getJSONArray("albums");
                if (albumsListParam.size() > 0) {
                    for (int i = 0; i < albumsListParam.size(); i++) {
                        List<String> list = new ArrayList<>();
                        JSONObject paramJSONObject = albumsListParam.getJSONObject(i);
                        Integer albumId = paramJSONObject.getInteger("albumId");
                        String title = paramJSONObject.getString("title");
                        String link = paramJSONObject.getString("link");
                        //拼接url书籍地址
                        StringBuilder sbUrl = new StringBuilder();
                        sbUrl.append(homePageUrl.substring(0,homePageUrl.length()-1));
                        sbUrl.append(link);
//                        String audioBookUrl = homePageUrl+link;
                        list.add(title);
                        list.add(sbUrl.toString());
                        map.put(albumId,list);
                    }
                }
            }
        }
        return map  ;
    }

    /**
     * @Description:获取章节信息
     * @Author:中国蚂蚁技术有限公司
     * @Date: 2020/9/5 17:09
     * @Param:  [] https://www.ximalaya.com/revision/album/v1/getTracksList?albumId=41021673&pageNum=15
     * @return: java.lang.String
     * */
    public static Map<Integer,List<String>> getChapterInfo(Integer albumId, Integer pageNum){
        Map<Integer,List<String>> map = new HashMap<>();
        StringBuilder getSectionUrl = new StringBuilder();
        String sectionInfo = PropertiesUtil.getDocking("QUERY_LIST_SECTION_INFO");
        getSectionUrl.append(homePageUrl);
        getSectionUrl.append(sectionInfo);
        getSectionUrl.append("albumId=");
        getSectionUrl.append(albumId);
        getSectionUrl.append("&pageNum=");
        getSectionUrl.append(pageNum);
        //拼接请求路径
        System.out.println("获取章节请求路径:"+getSectionUrl.toString());
        //发送请求 获取响应 解析响应
        String responseParam = sendRequestGet(getSectionUrl.toString());
        if(responseParam.contains("{")){
            //响应成功 补充日志 进行json转换
            JSONObject parseObject = JSONObject.parseObject(responseParam);
            if ("200".equals(parseObject.getString("ret"))){
                JSONObject dataSection = JSONObject.parseObject(parseObject.getString("data"));
                if (dataSection.size()>0){
                    JSONArray tracks = dataSection.getJSONArray("tracks");
                    for (int i = 0; i < tracks.size(); i++) {
                        JSONObject tracksJSONObject = tracks.getJSONObject(i);
                        List<String> list = new ArrayList<>();
                        StringBuilder sb = new StringBuilder();
                        if (tracksJSONObject.getInteger("tag")==1||tracksJSONObject.getInteger("tag")==0){
                            Integer trackId = tracksJSONObject.getInteger("trackId");
                            String src = audioBookUrl(trackId);
                            String title = tracksJSONObject.getString("title");
                            System.out.println(tracksJSONObject.getString("createDateFormat"));
                            String updateDateFormat = dateFormats(tracksJSONObject.getString("createDateFormat"));
                            String url = tracksJSONObject.getString("url");
                            sb.append(homePageUrl.substring(0,homePageUrl.length()-1));
                            sb.append(url);
                            list.add(title);
                            list.add(src);
                            list.add(updateDateFormat);
                            list.add(sb.toString());
                            map.put(trackId,list);
                        }else {
                            continue;
                        }
                    }

                }
            }

        }
        return map;
    }

    /**
     * @Description：获取分页信息
     * @Author:中国蚂蚁技术有限公司
     * @Date: 2020/9/6 13:37
     * @Param:https://www.ximalaya.com/revision/album?albumId=3493173
     * @return:
     * */
    public static PageDevice getPageInfo(Integer albumId){
        StringBuilder url = new StringBuilder();
        String trackIdUrl = PropertiesUtil.getDocking("QUERY_LIST_TRACK_ID");
        url.append(homePageUrl);
        url.append(trackIdUrl);
        url.append(albumId);
        System.out.println("获取章节id请求路径:"+url.toString());
        //发送请求获取返回值
        String responseParam = sendRequestGet(url.toString());
        if (responseParam.contains("{")){
            JSONObject parseObject = JSONObject.parseObject(responseParam);
            if (parseObject.getInteger("ret")==200){
                JSONObject dataParam = parseObject.getJSONObject("data");
                JSONObject tracksInfo = dataParam.getJSONObject("tracksInfo");
                //获取章节总条数
                String trackTotalCount = tracksInfo.getString("trackTotalCount");
                //获取每页条数
                String pageSize = tracksInfo.getString("pageSize");
                //获取开始页数
                String pageNum = tracksInfo.getString("pageNum");
                PageDevice pageDevice = new PageDevice(trackTotalCount,pageSize);
                pageDevice.setTotalCount(trackTotalCount);
                pageDevice.setPageSize(pageSize);
                pageDevice.setStartPageNum(pageNum);
                return pageDevice;
            }
        }
        return null;
    }

    /**
     * @Description:最关键的一步获取有声书路径
     * @Author:中国蚂蚁技术有限公司
     * @Date: 2020/9/5 18:43
     * @Param:  [] https://www.ximalaya.com/41136388&ptype=1
     * @return: java.lang.String
     * */
    public static String audioBookUrl(Integer trackId){
        StringBuilder audioUrl = new StringBuilder();
        String listAudioBook = PropertiesUtil.getDocking("QUERY_LIST_AUDIO_BOOK");
        audioUrl.append(homePageUrl);
        audioUrl.append(listAudioBook);
        audioUrl.append(trackId);
        audioUrl.append("&ptype=1");
        System.out.println("请求路径:"+audioUrl.toString());
        //发送请求
        String responseParam = sendRequestGet(audioUrl.toString());
        System.out.println("打印返回值:"+responseParam);
        if (responseParam.contains("{")){
            JSONObject parseObject = JSONObject.parseObject(responseParam);
            if (parseObject.getInteger("ret")==200){
                JSONObject data = parseObject.getJSONObject("data");
                String src = data.getString("src");
                return src;
            }
        }

        return "请求失败返回"+responseParam;
    }

    /**
    * @Description:发送请求Get
    * @Author:wkl
    * @Date:2020/9/4
    * @param:
    * @return:java.lang.String
    */
    public static String sendRequestGet(String url){
        RedisUtil.setValue("cookie",cookie,3600);
        String token = "";
        if (!RedisUtil.hasKey("token")){
            token = getToken();
            RedisUtil.setValue("token",token,1800);
        }
        token = RedisUtil.getValue("token");
        try {
        //模拟浏览器
        HttpClient httpClient = HttpClientBuilder.create().build();
        //设置请求头
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("content-type","application/x-www-form-urlencoded;charset=UTF-8");
        httpGet.setHeader("user-agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4128.3 Safari/537.36");
        httpGet.setHeader("xm-sign",token);
        httpGet.setHeader("cookie",RedisUtil.getValue("cookie"));
        HttpResponse response = null;
            response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode()==200){
                HttpEntity httpEntity = response.getEntity();
                String content= EntityUtils.toString(httpEntity,"utf8");
                return content;
            }else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
    * @Description:自定义响应
    * @Author:wkl
    * @Date:2020/9/4
    * @param:
    * @return:
    */
    private static ResponseHandler<ResponseResult> responseHandler = new ResponseHandler<ResponseResult>() {
        // 自定义响应处理
        public ResponseResult handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
            int code = response.getStatusLine().getStatusCode();
            String message = null;
            String result = null;
            HttpEntity entity=response.getEntity();
            if(entity!=null){
                String charset= EntityUtils.getContentCharSet(entity)==null?CHARSET_ENCODING:EntityUtils.getContentCharSet(entity);
                result = new String(EntityUtils.toByteArray(entity), charset);
            }
            return new ResponseResult(code, message, result);
        }
    };

    /**
     * @Description:获取更新时间
     * @Author:中国蚂蚁技术有限公司
     * @Date: 2020/9/6 12:51
     * @Param:  []
     * @return: java.lang.String
     * */
    public static String dateFormats(String dates){
        String time = StringUtils.isEmpty(dates)?"0天":dates;
        Integer numberDay =0;
        calendar.setTime(date);
        //月份转换 3月前
        if (time.contains("分钟")){
            numberDay = Integer.parseInt(time.substring(0,time.indexOf("分钟")));
            calendar.add(Calendar.MINUTE,-numberDay);
        }else if (time.contains("小时")){
            numberDay = Integer.parseInt(time.substring(0,time.indexOf("小时")));
            calendar.add(Calendar.HOUR,-numberDay);
        }else if (time.contains("天")){
            numberDay = Integer.parseInt(time.substring(0,time.indexOf("天")));
            calendar.add(Calendar.DATE,-numberDay);
        }else if (time.contains("月")){
            numberDay=Integer.parseInt(time.substring(0,time.indexOf("月")));
            calendar.add(Calendar.MONTH,-numberDay);
        }else {
            numberDay=Integer.parseInt(time.substring(0,time.indexOf("年")));
            calendar.add(Calendar.YEAR,-numberDay);
        }
        return DateUtil.format(calendar.getTime(),"yyyy-MM-dd HH:mm:ss") ;
    }
    
    /**
     * @Description:获取vip路径的时候可以使用https://mpay.ximalaya.com/mobile/track/pay/318571695?device=pc url 也能访问路径
     * @Author:中国蚂蚁技术有限公司
     * @Date: 2020/9/17 21:54
     * @Param:  String trackId  章节id
     * @return: java.lang.String
     * */
    private static VipUrlDto getVipUrlParam(String trackId){
        VipUrlDto urlDto = new VipUrlDto();
        StringBuilder vipUrl = new StringBuilder();
        String vipAudioBookUrl = PropertiesUtil.getDocking("QUERY_VIP_AUDIO_BOOK_URL");
        vipUrl.append(vipAudioBookUrl);
        vipUrl.append(trackId);
        vipUrl.append("?device=pc");
        FileReadWriteUtil.printLog("获取vip有声书返回参数路径 ===》"+vipUrl.toString());
        String responseParam = HttpClientUtils.sendRequestGet(vipUrl.toString());
        System.out.println("响应结果："+responseParam);
        //判断过滤
        if ("".equals(responseParam)||!responseParam.contains("{")){
            return null;
        }
        JSONObject parseObject = JSONObject.parseObject(responseParam);
        if(parseObject.getInteger("ret")==0){
            String domain = parseObject.getString("domain");
            String apiVersion = parseObject.getString("apiVersion");
            String duration = parseObject.getString("duration");
            Integer seed = parseObject.getInteger("seed");
            String ep = parseObject.getString("ep");
            String fileId = parseObject.getString("fileId");
            urlDto.setDomain(domain);
            urlDto.setApiVersion(apiVersion);
            urlDto.setDuration(duration);
            urlDto.setSeed(seed);
            urlDto.setEp(ep);
            urlDto.setFileId(fileId);
        }
        return urlDto;
    }

    /**
     * @Description:VIP拼接url
     * @Author:中国蚂蚁技术有限公司
     * @Date: 2020/9/17 21:56
     * @Param:  String pathUrl,List<String> param
     * @return: java.lang.String
     * */
    public static String vipAudioUrl(String trackId) {
        //拼接url
        StringBuilder url = new StringBuilder();
        //获取VipDto
        VipUrlDto vipUrlParam = getVipUrlParam(trackId);
        String pathDec = VipEncryption.pathDec(vipUrlParam.getSeed(), vipUrlParam.getFileId());
        List<String> paramDec = VipEncryption.paramDec(vipUrlParam.getEp());
        url.append(vipUrlParam.getDomain());
        url.append("/download/");
        url.append(vipUrlParam.getApiVersion());
        url.append(pathDec);
        url.append("?buy_key=");
        url.append(paramDec.get(0));
        url.append("&sign=");
        url.append(paramDec.get(1));
        url.append("&token=");
        url.append(paramDec.get(2));
        url.append("&timestamp=");
        url.append(paramDec.get(3));
        url.append("&duration=");
        url.append(vipUrlParam.getDuration());
        FileReadWriteUtil.printLog("vip有声书路径:"+url.toString());
        return url.toString();
    }

    public static void downAudioT(){
        List<Object> allKeyName = RedisUtil.getAllKey("name:*");
        List<Object> allKeyTackId = RedisUtil.getAllKey("tackId:*");
        for (int i = 0; i < allKeyTackId.size(); i++) {
            String fileName = createFile((String)allKeyName.get(i));
            try {
                FileReadWriteUtil.downloadSource((String)allKeyTackId.get(i), fileName);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
